package com.yc.pre.config.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author baozhuangyu
 * @Date 2020/11/25  19:00
 */
@Slf4j
public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UsernamePasswordDetailsService userDetailsService;

//    @Autowired
//    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Bean
    private BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    public void setUserDetailsService(UsernamePasswordDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    protected UsernamePasswordDetailsService getUserDetailsService() {
        return this.userDetailsService;
    }


    /**
     * 实现AuthenticationProvider类中的两个方法
     * <p>
     * 1，授权
     */

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
        PreSignUserDetails preSignUserDetails = (PreSignUserDetails) userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());
        if (preSignUserDetails == null) {
            throw new InternalAuthenticationServiceException("无法根据账号获取用户信息");
        }
        //测密码
        CharSequence credentials = (CharSequence) authentication.getCredentials();
        String encode = bCryptPasswordEncoder().encode(credentials);
        final boolean matches = bCryptPasswordEncoder().matches((CharSequence) authentication.getCredentials(), preSignUserDetails.getPassword());

        if (matches) {
            UsernamePasswordAuthenticationToken authenticationResult = new UsernamePasswordAuthenticationToken(preSignUserDetails, authentication.getCredentials());
            authenticationResult.setDetails(authenticationToken.getDetails());
            return authenticationResult;
        }else {
            throw new BadCredentialsException("密码错误");
        }
    }

    /**
     * 2，通过不同的Token进行不同的Provider验证
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    }
}
